package com.limboline.bssystem.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.limboline.bssystem.entity.CommodityEntity;
import com.limboline.bssystem.entity.CommodityVO;
import com.limboline.bssystem.entity.CustomerEntity;
import com.limboline.bssystem.mapper.CommodityEntityMapper;
import com.limboline.bssystem.mapper.CustomerEntityMapper;
import com.limboline.bssystem.service.CommodityService;
import com.limboline.bssystem.util.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.*;

@Service
public class CommodityServiceImpl implements CommodityService {
    public static Logger logger = LoggerFactory.getLogger(CommodityServiceImpl.class);
    public static final Set<String> ALLOW_FILE_SUFFIX = new HashSet<>(Arrays.asList("jpg", "png", "jpeg", "gif"));
    private static final String dirPath = "local/img/";

    @Value("${gitee.bucket.url}")
    private String url;

    @Value("${gitee.bucket.api}")
    private String api;

    @Value("${gitee.bucket.access-token}")
    private String accessToken;


    @Autowired
    RestTemplate restTemplate;
    @Autowired(required = false)
    CommodityEntityMapper commodityEntityMapper;

    @Autowired(required = false)
    CustomerEntityMapper customerEntityMapper;

    @Override
    public boolean uploadImg(MultipartFile multipartFile) {

        String suffix = this.getSuffix(multipartFile.getOriginalFilename()).toLowerCase();
        if (!ALLOW_FILE_SUFFIX.contains(suffix)) {
            throw new IllegalArgumentException("不支持的文件后缀：" + suffix);
        }

        String filePath = dirPath + multipartFile.getOriginalFilename();
        logger.info("upload to Gitee: {}", filePath);
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("message", "file upload");
            jsonObject.put("content", Base64.getEncoder().encodeToString(multipartFile.getBytes()));
            jsonObject.put("access_token", accessToken);


            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
            httpHeaders.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);

            ResponseEntity<String> responseEntity = this.restTemplate.exchange(this.api + filePath, HttpMethod.POST,
                    new HttpEntity<String>(jsonObject.toString(), httpHeaders), String.class);
            logger.info("uploadSuccess: {}", responseEntity.getBody());
            if (responseEntity.getStatusCode().isError()) {

                logger.error("CommodityServiceImpl.uploadImg failed");
                return false;
            }
            return true;
        }catch (IOException e){
            logger.error("CommodityServiceImpl.uploadImg has an error: {}", e);
            return false;
        }
    }

    @Override
    public Integer submitCommodity(String data) {
        CommodityEntity commodityEntity = new CommodityEntity();
        JSONObject obj= JSON.parseObject(data);
        commodityEntity.setTitle(obj.getString("title"));
        commodityEntity.setDescription(obj.getString("detail"));
        commodityEntity.setSummary(obj.getString("summary"));
        commodityEntity.setPrice(obj.getDouble("price"));

        if(obj.getString("file") == null || "".equals(obj.getString("file"))){
            commodityEntity.setPicUrl(obj.getString("url"));
        }else{
            commodityEntity.setPicUrl(url + dirPath + obj.getString("file"));
        }
        if(obj.getBoolean("isFirst")){
            commodityEntity.setPublishDate(obj.getLong("publishDate"));
            commodityEntityMapper.insertSelective(commodityEntity);
            return commodityEntityMapper.selectByPublishDate(obj.getLong("publishDate")).getId();
        }else{
            commodityEntity.setId(obj.getInteger("id"));
            commodityEntity.setModifyDate(obj.getLong("modifyDate"));
            commodityEntityMapper.updateByPrimaryKeySelective(commodityEntity);
            return commodityEntity.getId();
        }
    }


    @Override
    public void edit(ModelAndView modelAndView, Integer type) {
        List<CommodityEntity> commodityEntities = commodityEntityMapper.findAll();
        List<CommodityVO> commodityVOS = new ArrayList<>();
        JSONObject jsonObject = new JSONObject();
        if(type == null || type != 1){
            jsonObject.put("type", 0);
            for(CommodityEntity commodityEntity : commodityEntities){
                CommodityVO commodityVO = new CommodityVO();
                BeanUtils.copyProperties(commodityEntity, commodityVO);
                commodityVO.setPurchased(commodityEntity.getPurchaseDate() != null);
                commodityVOS.add(commodityVO);
            }
        }else{
            jsonObject.put("type", 1);
            for(CommodityEntity commodityEntity : commodityEntities){
                CommodityVO commodityVO = new CommodityVO();
                BeanUtils.copyProperties(commodityEntity, commodityVO);
                commodityVO.setPurchased(commodityEntity.getPurchaseDate() != null);
                if(!commodityVO.isPurchased()){
                    commodityVOS.add(commodityVO);
                }
            }
        }
        JSONArray array = JSONArray.parseArray(JSON.toJSONString(commodityVOS));
        jsonObject.put("array", array);
        modelAndView.addObject("commodity", jsonObject.toJSONString());
    }

    @Override
    public void show(ModelAndView modelAndView, Integer type, Integer id) {
        CommodityEntity entity = commodityEntityMapper.selectByPrimaryKey(id);
        modelAndView.addObject("commodity", entity);
        if(type == 2){
            CustomerEntity customerEntity = customerEntityMapper.selectByCid(entity.getId());
            if(customerEntity != null){
                modelAndView.addObject("purchasedPrice", customerEntity.getPrice());
            }
        }
    }

    @Override
    public boolean delete(Integer id) {
        commodityEntityMapper.deleteByPrimaryKey(id);
        CustomerEntity customerEntity = customerEntityMapper.selectByCid(id);
        if(customerEntity != null){
            customerEntityMapper.deleteByPrimaryKey(customerEntity.getId());
        }
        return true;
    }

    @Override
    public String check(String userName, String password) {
        String sellerName = getMD5("seller");
        String sellerPassword = getMD5("relles");
        String buyerName = getMD5("buyer");
        String buyerPassword = getMD5("reyub");
        if(userName.equals(sellerName) && password.equals(sellerPassword)){
            State.getInstance().setState(1);
            return "Seller";
        }else if(userName.equals(buyerName) && password.equals(buyerPassword)){
            State.getInstance().setState(2);
            return "Buyer";
        }else{
            State.getInstance().setState(0);
            return "None";
        }
    }


    /**
     * 获取文件的后缀
     * @param fileName
     * @return
     */
    protected String getSuffix(String fileName) {
        int index = fileName.lastIndexOf(".");
        if (index != -1) {
            String suffix = fileName.substring(index + 1);
            if (!suffix.isEmpty()) {
                return suffix;
            }
        }
        throw new IllegalArgumentException("非法的文件名称：" + fileName);
    }

    protected String getMD5(String data){
        try {
            // 生成一个MD5加密计算摘要
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 计算md5函数
            md.update(data.getBytes());
            // digest()最后确定返回md5 hash值，返回值为8位字符串。因为md5 hash值是16位的hex值，实际上就是8位的字符
            // BigInteger函数则将8位的字符串转换成16位hex值，用字符串来表示；得到字符串形式的hash值
            //一个byte是八位二进制，也就是2位十六进制字符（2的8次方等于16的2次方）
            return new BigInteger(1, md.digest()).toString(16);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
